package model;

import java.util.Iterator;
import java.util.NoSuchElementException;


/**
 * CustomArray is a dynamic array. Add and remove objects without concerning about the length of the array. A basic ArrayList.
 * @author Group 20
 * @param <ObjectType> Add any kind of object
 */
public class CustomArray<ObjectType> implements Iterable<ObjectType>, Iterator<ObjectType> 
{ 
	/**
	 * Main array for storing any kind of object
	 */
	private Object data[] = new Object[0]; 
	
	/**
	 * Count variable for iterate purposes
	 */
	private int count = 0; 
 
	/**
	 * Length of CustomArray  
	 * @return Returns the number of objects stored
	 */
	public int size()
	{
		return data.length;
	}
  
	/**
	 * Adds and stores object in the dynamic array  
	 * @param objectType: Same object type as type of CustomArray
	 */
	public void add(ObjectType objectType)
	{
		Object newData[] = new Object[data.length + 1];
	  
		for (int i = 0; i < data.length; i++) 
			newData[i] = data[i]; 
		 
		newData[newData.length - 1] = objectType;
		data = newData;
	}	
	
	/**
	 * Erases all objects store
	 */
	public void clear()
	{
		data = new Object[0];
	}
	
	/**
	 * Converts all objects stored, to strings.
	 * @return Array of strings.
	 */
	public String[] returnStringArray()
	{
		String[] stringArray = new String[data.length];
		
		for (int i = 0; i < data.length; i++) 
		{
			stringArray[i] = (String)data[i];
		}
		return stringArray;
	}
  
	/**
	 * Determines while iterating if there are any objects left.
	 */
	public boolean hasNext() 
	{ 
		if(count < data.length) 
			return true; 
    
		else
		{
			count = 0;
			return false; 	
		}
    } 
 
	/**
	 * Returns current object while iterating.
	 * @return An object of specific type.
	 */
	public ObjectType next() 
	{ 
		if(count == data.length)  
			throw new NoSuchElementException(); 
 
		count++; 
		@SuppressWarnings("unchecked")
		ObjectType type = (ObjectType) data[count-1];
		return type; 
	} 
 
	public void remove(){} 
  
	/**
	 * Removes all objects stored with same reference.
	 * @param objectType: Your own specific object type.
	 */
	public void remove(ObjectType objectType)
	{
		Object newData[] = new Object[data.length];
	  
		// Copy to new array without this object
		int h = 0;
		for (int i = 0; i < data.length; i++)
		{
			if (objectType != data[i])
			{
				newData[h] = data[i];
				h++;
			}	
		}
	  
	 // Count new length for data array
	 int i = 0;
	 for(Object object : newData)
	 {
		 if (object !=null)
		 i++;
	 }
	  
	 // Fill
	 Object newData2[] = new Object[i];
	 int k = 0;
	 for (int j = 0; j < newData.length; j++) 
	 {
		if (newData[j] != null)
		{
			newData2[k] = newData[j];
			k++;
		}
	 }
	
	 data = newData2;
  }
	/**
	 * Returns a specific object pointed out in the main array.
	 * @param indexNo: Index number
	 * @return An object
	 */
	public Object get(int indexNo)
	{
		return data[indexNo];
	}
	
 
  public Iterator<ObjectType> iterator() 
  { 
	  return this; 
  } 
  
} 